From 7ac0b750e539248c5ce73d000e9fc509f37e4ff6 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Thu, 23 Feb 2006 15:22:19 +0000 Subject: [PATCH] Move the gate page (vsyscall) out of the fixmap area into user address space, just below PAGE_OFFSET. From: Gerd Hoffmann Signed-off-by: Christian Limpach --- .../arch/i386/kernel/asm-offsets.c | 3 +- .../arch/i386/kernel/sysenter.c | 76 +++++++++++++++++-- .../arch/i386/mm/pgtable-xen.c | 1 - linux-2.6-xen-sparse/include/asm-i386/a.out.h | 2 +- linux-2.6-xen-sparse/include/asm-i386/elf.h | 7 +- .../include/asm-i386/mach-xen/asm/fixmap.h | 9 --- .../include/asm-i386/mach-xen/asm/page.h | 2 + 7 files changed, 82 insertions(+), 18 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/asm-offsets.c b/linux-2.6-xen-sparse/arch/i386/kernel/asm-offsets.c index fa4f25dada..3c4a0f46eb 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/asm-offsets.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/asm-offsets.c @@ -13,6 +13,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -70,5 +71,5 @@ void foo(void) #endif DEFINE(PAGE_SIZE_asm, PAGE_SIZE); - DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL)); + DEFINE(VSYSCALL_BASE, VSYSCALL_BASE); } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c index 3bd61e7bf0..99193bb47f 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -47,25 +48,90 @@ void enable_sep_cpu(void) */ extern const char vsyscall_int80_start, vsyscall_int80_end; extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; +static void *syscall_page; int __init sysenter_setup(void) { - void *page = (void *)get_zeroed_page(GFP_ATOMIC); - - __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC); + syscall_page = (void *)get_zeroed_page(GFP_ATOMIC); #ifdef CONFIG_X86_SYSENTER if (boot_cpu_has(X86_FEATURE_SEP)) { - memcpy(page, + memcpy(syscall_page, &vsyscall_sysenter_start, &vsyscall_sysenter_end - &vsyscall_sysenter_start); return 0; } #endif - memcpy(page, + memcpy(syscall_page, &vsyscall_int80_start, &vsyscall_int80_end - &vsyscall_int80_start); return 0; } + +static struct page* +syscall_nopage(struct vm_area_struct *vma, unsigned long adr, int *type) +{ + struct page *p = virt_to_page(adr - vma->vm_start + syscall_page); + get_page(p); + return p; +} + +/* Prevent VMA merging */ +static void syscall_vma_close(struct vm_area_struct *vma) +{ +} + +static struct vm_operations_struct syscall_vm_ops = { + .close = syscall_vma_close, + .nopage = syscall_nopage, +}; + +/* Setup a VMA at program startup for the vsyscall page */ +int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) +{ + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + int ret; + + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!vma) + return -ENOMEM; + + memset(vma, 0, sizeof(struct vm_area_struct)); + /* Could randomize here */ + vma->vm_start = VSYSCALL_BASE; + vma->vm_end = VSYSCALL_BASE + PAGE_SIZE; + /* MAYWRITE to allow gdb to COW and set breakpoints */ + vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; + vma->vm_flags |= mm->def_flags; + vma->vm_page_prot = protection_map[vma->vm_flags & 7]; + vma->vm_ops = &syscall_vm_ops; + vma->vm_mm = mm; + + down_write(&mm->mmap_sem); + if ((ret = insert_vm_struct(mm, vma))) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return ret; + } + mm->total_vm++; + up_write(&mm->mmap_sem); + return 0; +} + +struct vm_area_struct *get_gate_vma(struct task_struct *tsk) +{ + return NULL; +} + +int in_gate_area(struct task_struct *task, unsigned long addr) +{ + return 0; +} + +int in_gate_area_no_task(unsigned long addr) +{ + return 0; +} diff --git a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c index 923ad17df5..7a32295ec6 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c @@ -194,7 +194,6 @@ void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags) } switch (idx) { case FIX_WP_TEST: - case FIX_VSYSCALL: #ifdef CONFIG_X86_F00F_BUG case FIX_F00F_IDT: #endif diff --git a/linux-2.6-xen-sparse/include/asm-i386/a.out.h b/linux-2.6-xen-sparse/include/asm-i386/a.out.h index ab17bb8e54..66db22938f 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/a.out.h +++ b/linux-2.6-xen-sparse/include/asm-i386/a.out.h @@ -19,7 +19,7 @@ struct exec #ifdef __KERNEL__ -#define STACK_TOP TASK_SIZE +#define STACK_TOP (TASK_SIZE - 3*PAGE_SIZE) #endif diff --git a/linux-2.6-xen-sparse/include/asm-i386/elf.h b/linux-2.6-xen-sparse/include/asm-i386/elf.h index 4153d80e4d..b08208c06b 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/elf.h +++ b/linux-2.6-xen-sparse/include/asm-i386/elf.h @@ -129,11 +129,16 @@ extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs) -#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL)) +#define VSYSCALL_BASE (PAGE_OFFSET - 2*PAGE_SIZE) #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE) #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall) extern void __kernel_vsyscall; +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES +struct linux_binprm; +extern int arch_setup_additional_pages(struct linux_binprm *bprm, + int executable_stack); + #define ARCH_DLINFO \ do { \ NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \ diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h index 1510d1c240..190bc2df59 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/fixmap.h @@ -53,7 +53,6 @@ */ enum fixed_addresses { FIX_HOLE, - FIX_VSYSCALL, #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif @@ -123,14 +122,6 @@ extern void __set_fixmap( #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) -/* - * This is the range that is readable by user mode, and things - * acting like user mode such as get_user_pages. - */ -#define FIXADDR_USER_START (__fix_to_virt(FIX_VSYSCALL)) -#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) - - extern void __this_fixmap_does_not_exist(void); /* diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h index 476ca434c7..a923361ea2 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h @@ -317,6 +317,8 @@ extern int page_is_ram(unsigned long pagenr); #define virt_to_mfn(v) (pfn_to_mfn(__pa(v) >> PAGE_SHIFT)) #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) +#define __HAVE_ARCH_GATE_AREA 1 + #endif /* __KERNEL__ */ #include -- 2.30.2